﻿@using Plotly.Blazor.LayoutLib
@using Plotly.Blazor.Traces.ScatterLib
@using System.Diagnostics

<PlotlyChart style="height: 60vh; min-height: 350px" @bind-Config="config" @bind-Layout="layout" @bind-Data="data" @ref="chart" />

<div class="text-right">
    <button type="button" class="btn btn-primary" @onclick="() => chart.Clear()">Clear</button>
    <button type="button" class="btn btn-primary" @onclick="() => DeleteScatter()">Pop</button>
    <button type="button" class="btn btn-primary" @onclick="() => AddScatter()">Push</button>
    <button type="button" class="btn btn-primary" @onclick="() => Restyle()">Rename First</button>
    <button type="button" class="btn btn-primary" @onclick="() => PrependData()">Prepend First</button>
    <button type="button" class="btn btn-primary" @onclick="() => ExtendData()">Extend First</button>
    <button type="button" class="btn btn-primary" @onclick="() => PrependWithLimit()">Prepend First (Max. 100)</button>
    <button type="button" class="btn btn-primary" @onclick="() => ExtendWithLimit()">Extend First (Max. 100)</button>
</div>

@code
{
    PlotlyChart chart;

    Config config = new Config
    {
        Responsive = true
    };

    Layout layout = new Layout
    {
        Title = new Title
        {
            Text = "Scatter"
        },
        YAxis = new List<YAxis>
    {
            new YAxis
            {
                Title = new LayoutLib.YAxisLib.Title
                {
                    Text = "Scatter Unit"
                }
            }
        }
    };

    IList<ITrace> data = new List<ITrace>{
        new Scatter
        {
            Name = "ScatterTrace",
            Mode = ModeFlag.Lines | ModeFlag.Markers,
            X = new List<object>(),
            Y = new List<object>()
        }
    };

    private async Task ExtendData(int count = 100)
    {
        if (!(chart.Data.FirstOrDefault() is Scatter scatter)) return;

        var max = (int?)scatter.X?.Max();
        var (x, y) = Helper.GenerateData(max + 1 ?? 0, max + 1 + count ?? count);


        if (!scatter.X.Any() || !scatter.Y.Any())
        {
            scatter.X.AddRange(x);
            scatter.Y.AddRange(y);
            await chart.React();
        }
        else
        {
            await chart.ExtendTrace(x, y, data.IndexOf(scatter));
        }
    }

    private async Task ExtendWithLimit(int count = 100, int limit = 100)
    {
        if (!(chart.Data.FirstOrDefault() is Scatter scatter)) return;

        var max = (int?)scatter.X?.Max();
        var (x, y) = Helper.GenerateData(max + 1 ?? 0, max + 1 + count ?? count);


        if (!scatter.X.Any() || !scatter.Y.Any())
        {
            scatter.X.AddRange(x);
            scatter.Y.AddRange(y);
            await chart.React();
        }
        else
        {
            await chart.ExtendTrace(x, y, data.IndexOf(scatter), limit);
        }
    }

    private async Task PrependWithLimit(int count = 100, int limit = 100)
    {
        if (!(chart.Data.FirstOrDefault() is Scatter scatter)) return;

        var min = (int?)scatter.X?.Min();
        var (x, y) = Helper.GenerateData(min - 1 ?? 0, min - 1 - count ?? count * -1);

        if (!scatter.X.Any() || !scatter.Y.Any())
        {
            scatter.X.AddRange(x);
            scatter.Y.AddRange(y);
            await chart.React();
        }
        else
        {
            await chart.PrependTrace(x, y, data.IndexOf(scatter), limit);
        }
    }

    private async Task PrependData(int count = 100)
    {
        if (!(chart.Data.FirstOrDefault() is Scatter scatter)) return;

        var min = (int?)scatter.X?.Min();
        var (x, y) = Helper.GenerateData(min - 1 ?? 0, min - 1 - count ?? count * -1);

        if (!scatter.X.Any() || !scatter.Y.Any())
        {
            scatter.X.AddRange(x);
            scatter.Y.AddRange(y);
            await chart.React();
        }
        else
        {
            await chart.PrependTrace(x, y, data.IndexOf(scatter));
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await ExtendData();
        }
    }

    private async Task Restyle()
    {
        var updateScatterChart = new Scatter
        {
            Name = "Restyled Name"
        };
        await chart.Restyle(updateScatterChart, 0);
    }

    private async Task DeleteScatter()
    {
        await chart.DeleteTrace(0);
    }

    private async Task AddScatter()
    {
        var (x, y) = Helper.GenerateData(0,100);
        await chart.AddTrace(new Scatter
        {

            Name = $"ScatterTrace{data.Count+1}",
            Mode = ModeFlag.Lines | ModeFlag.Markers,
            X = x,
            Y = y
        });
    }
}